package com.sino.operation.service.business;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.math.MathUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sino.operation.commons.ConstantValue;
import com.sino.operation.commons.commonEnum.ChargeInfoEnum;
import com.sino.operation.commons.commonEnum.ClassNameEnum;
import com.sino.operation.commons.commonEnum.TaskStateEnum;
import com.sino.operation.dto.Dto;
import com.sino.operation.dto.inner.IntBusAndAuthDto;
import com.sino.operation.dto.inner.PublicInfoDto;
import com.sino.operation.entity.*;
import com.sino.operation.param.ChargeSubTradeParam;
import com.sino.operation.param.inner.TaskCompleteAccountPublic;
import com.sino.operation.param.inner.TaskCompleteByAccountParam;
import com.sino.operation.param.out.CenterDataAccount;
import com.sino.operation.param.out.EscBodyByAccount;
import com.sino.operation.param.out.EscReceiveByCounterToAccount;
import com.sino.operation.peripheral.esc.request.*;
import com.sino.operation.peripheral.esc.request.core.EscAccountTest;
import com.sino.operation.peripheral.esc.request.core.EscCore2110Param;
import com.sino.operation.peripheral.esc.request.core.EscCore4010Param;
import com.sino.operation.peripheral.esc.request.core.EscCore4020Param;
import com.sino.operation.peripheral.esc.request.core.body.EscBodyCore2110;
import com.sino.operation.peripheral.esc.request.core.body.EscBodyCore4010;
import com.sino.operation.peripheral.esc.request.core.body.EscBodyCore4020;
import com.sino.operation.peripheral.esc.request.core.body.EscBodyCore4022;
import com.sino.operation.peripheral.esc.request.core.param.Core_4010_Listnm01Info_Param;
import com.sino.operation.peripheral.esc.request.core.param.Core_4010_Listnm02_Param;
import com.sino.operation.peripheral.esc.request.core.param.Core_4010_ListnmInfo_param;
import com.sino.operation.peripheral.esc.response.EscResSysHead;
import com.sino.operation.peripheral.esc.response.EscResponseDto;
import com.sino.operation.peripheral.esc.response.EscRet;
import com.sino.operation.peripheral.esc.response.core.EscCore2110Dto;
import com.sino.operation.peripheral.esc.response.core.EscCore4010Dto;
import com.sino.operation.peripheral.esc.response.core.EscCoreDto;
import com.sino.operation.peripheral.esc.response.core.body.*;
import com.sino.operation.service.core.entity.PostCoreRecive;
import com.sino.operation.util.*;
import com.sino.operation.vo.PublicInfo;
import com.sino.operation.vo.current.CurrentStartMarkParam;
import com.sino.operation.vo.current.FieldInformation;
import com.sino.operation.vo.current.InfoInput;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.runtime.parser.node.MathUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Title: Exec_710307
 * @Description: 活期开户
 * @Author dengls
 * @date 2021/10/21 10:38
 */
@Slf4j
public class Exec_710307 extends BaseAction {

    public Exec_710307(Map varMap, BizTranslist bizTranslist, SysAbMessage sysAbMessage, BizOperateLog bizOperateLog, Object registerTable, Object receiveParam) {
        super(varMap, bizTranslist, sysAbMessage, bizOperateLog, registerTable, receiveParam);
    }

    public Exec_710307(String journalNo, SysAbMessage sysAbMessage) {
        super(journalNo, sysAbMessage);
    }

    @Override
    public PersistenceUtil executeReception() throws Exception {
        EscReceiveByCounterToAccount escReceiveByCounterToAccount = (EscReceiveByCounterToAccount) this.receiveParam;
        PublicInfo publicInfo = escReceiveByCounterToAccount.getEscBodyByAccount().getPublicInfo();
        String date = publicInfo.getTranDate() + " " + publicInfo.getTranTimeStamp();
        String orgCode = publicInfo.getOrgCode();
        String orgName = publicInfo.getOrgName();
        String priority = null;
        String journalNo = this.bizTranslist.getJournalNo();
        String transCode = this.bizTranslist.getTransCode();
        String launchTellerId = this.bizTranslist.getLaunchTellerId();
        String launchTellerName = this.bizTranslist.getLaunchTellerName();
        String transType = this.bizTranslist.getTransType();


        ValueOperations<String, String> opsForValue = this.redis.opsForValue();
        priority = opsForValue.get(transCode + "-priority");
        if (StringUtils.isBlank(priority) || StringUtils.isEmpty(priority)) {
            QueryWrapper<BizManagerTrans> wrapper = new QueryWrapper<>();
            wrapper.eq("trans_code", transCode);
            BizManagerTrans bizManagerTrans = this.bizManagerTransMapper.selectOne(wrapper);
            if (ObjectUtil.isNotNull(bizManagerTrans)) {
                priority = bizManagerTrans.getDpriority();
                opsForValue.set(transCode + "-priority", priority);
            }

        }

        varMap.put("priority", priority);
        varMap.put("journal_no", this.bizTranslist.getJournalNo());
        List<InfoInput> infoInputs = escReceiveByCounterToAccount.getEscBodyByAccount().getCenterDataAccount().getInfoInputs();
        //取出网点发送到集中作业的报文值
        Map map = accountStartTest.getMap(escReceiveByCounterToAccount);
        //注册资金币种
        String zczjbz = (String) map.get("rgstn_cptl_ccy");
        //是否外汇监管标志
        String wgzhbs = (String) map.get("wthr_fx_rgln_flg");
        //核准件编号
        String hzjbh = (String) map.get("aprvl_instru_num");
        //外管账户性质
        String wgzhxz = (String) map.get("fx_mgmt_acct_charic");
        //账户性质
        String zhxz = (String) map.get("acct_clasf");
        //客户名称
        String khmc = (String) map.get("cust_nm");

        if (!"156".equals(zczjbz) || "1".equals(wgzhbs) || ObjectUtil.isNotNull(hzjbh)) {
            //走外管岗
            varMap.put("externel", "Y");
            varMap.put("tellerPost", "206");
        } else {
            varMap.put("externel", "N");
            varMap.put("tellerPost", "203");
        }
        varMap.put("priority", priority);
        //创建登记簿表并添加数据
        BizAccountmanageInfo bizAccountmanageInfo = BizAccountmanageInfo.builder().journalNo(journalNo).bsty(transType)
                .tellerCode(launchTellerId).tellerName(launchTellerName)
                .trandate(date).cyno(zczjbz == null ? "" : zczjbz).orgCode(orgCode).orgName(orgName)
                .cunm(khmc == null ? "" : khmc).bsty(zhxz == null ? "" : zhxz).brfg(wgzhxz == null ? "" : wgzhxz).build();
        this.persistence.addEntity(bizAccountmanageInfo);
        return this.persistence;
    }

    //外管1提交
    public PersistenceUtil executeIntBusRun1() throws Exception {
        return this.persistence;
    }

    //外管2提交
    public PersistenceUtil executeIntBusRun2() throws Exception {
        return this.persistence;
    }

    @Override
    public PersistenceUtil executeAuth() throws Exception {
        TaskCompleteByAccountParam taskCompleteByAccountParam = (TaskCompleteByAccountParam) this.receiveParam;
        TaskCompleteAccountPublic taskCompleteAccountPublic = taskCompleteByAccountParam.getTaskCompleteAccountPublic();
        String completeMark = taskCompleteAccountPublic.getCompleteMark();
        List<InfoInput> infoInputs = taskCompleteByAccountParam.getInfoInputs();
        String messageAccept = this.sysAbMessage.getMessageAccept();
        EscReceiveByCounterToAccount escReceiveByCounterToAccount = JSONUtil.toBean(JSONUtil.parseObj(messageAccept), EscReceiveByCounterToAccount.class);
        CenterDataAccount centerDataAccount = escReceiveByCounterToAccount.getEscBodyByAccount().getCenterDataAccount();
        centerDataAccount.setInfoInputs(infoInputs);
        EscBodyByAccount escBodyByAccount = escReceiveByCounterToAccount.getEscBodyByAccount();
        escBodyByAccount.setCenterDataAccount(centerDataAccount);
        escReceiveByCounterToAccount.setEscBodyByAccount(escBodyByAccount);
        String jsonStr = JSONUtil.toJsonStr(escReceiveByCounterToAccount);
        sysAbMessage.setMessage(jsonStr);
        sysAbMessage.setMessageAuth(jsonStr);
        this.bizTranslist.setBackFlag(completeMark);//保存提交标志
        if (ConstantValue.CONDITION_PASS.equals(completeMark)) {
            BizAddImage bizAddImage = new BizAddImage();
            bizAddImage.setId(StringUtil.getId());
            bizAddImage.setJournalNo(taskCompleteAccountPublic.getJournalNo());
            bizAddImage.setStartTeller(taskCompleteAccountPublic.getCenterTellerNo());
            bizAddImage.setStartTellerName(taskCompleteAccountPublic.getCenterTellerName());
            bizAddImage.setStartDate(TimeUtil.getStandardTime());
            bizAddImage.setState("0");//默认未补扫
            bizAddImage.setNoPassReason(taskCompleteAccountPublic.getReason());
            persistence.addEntity(bizAddImage);
        }
        varMap.put("back", "N");
        return this.persistence;
    }

    @Override
    public PersistenceUtil executeNetwork() throws Exception {
        return this.persistence;
    }

    @Override
    public PersistenceUtil executeBack() throws Exception {
        varMap.put("back", "N");
        return this.persistence;
    }

    @Override
    public Dto executeGetTaskList(NetHandle netHandle) {
        return new Dto();
    }

    @Override
    public PersistenceUtil executeTerminal() throws Exception {
        return this.persistence;
    }

    /**
     * @Description: ${整单岗获取任务}
     * param []
     * return java.lang.Object
     * author 北陈
     * date 2021/10/26 19:18
     */
    @Override
    public Object executeTotalEntryTask() throws Exception {
        return null;
    }

    /**
     * @Description: ${外管账户获取任务}
     * param []
     * return java.lang.Object
     * author 北陈
     * date 2021/10/26 19:18
     */
    public Object executeIntBusRunTask() throws Exception {
        return getAbMessage();
    }

    /**
     * @Description: ${授权岗获取任务}
     * param []
     * return java.lang.Object
     * author 北陈
     * date 2021/10/26 19:19
     */
    @Override
    public Object executeAuthTask() throws Exception {
        return getAbMessage();
    }

    public Object getAbMessage() {
        SysAbMessage sysAbMessage = this.sysAbMessageMapper.selectById(journalNo);
        String messageAccept = sysAbMessage.getMessageAccept();
        EscReceiveByCounterToAccount escReceiveByCounterToAccount = null;
        if (ObjectUtil.isNotNull(messageAccept)) {
            escReceiveByCounterToAccount = JSONUtil.toBean(JSONUtil.parseObj(messageAccept), EscReceiveByCounterToAccount.class);
            PublicInfo publicInfo = escReceiveByCounterToAccount.getEscBodyByAccount().getPublicInfo();
            String transCode = publicInfo.getTranCode();
            String orgCode = publicInfo.getOrgCode();
            String orgName = publicInfo.getOrgName();
            String imageId = publicInfo.getImageId();
            List<InfoInput> infoInputs = escReceiveByCounterToAccount.getEscBodyByAccount().getCenterDataAccount().getInfoInputs();
            return IntBusAndAuthDto.builder().infoInputs(infoInputs).build();

        }
        return null;
    }

    @Override
    public PersistenceUtil executeCharge() throws Exception {

        CoreHead coreHead = new CoreHead();
        coreHead.setReqResFlg("req");
        String journalNo = bizTranslist.getJournalNo();
        BizAccountmanageInfo bizAccountmanageInfo = accountmanageInfoMapper.selectById(journalNo);
        QueryWrapper<SysAbMessage> abMessageQueryWrapper = new QueryWrapper<>();
        abMessageQueryWrapper.eq("journal_no", journalNo);
        SysAbMessage sysAbMessage = sysAbMessageMapper.selectOne(abMessageQueryWrapper);
        String jsonStr = sysAbMessage.getMessageAccept();
        EscReceiveByCounterToAccount escReceiveByCounterToAccount = JSONUtil.toBean(jsonStr, EscReceiveByCounterToAccount.class);
        EscBodyByAccount escBodyByAccount = escReceiveByCounterToAccount.getEscBodyByAccount();
        List<InfoInput> infoInputs = escBodyByAccount.getCenterDataAccount().getInfoInputs();
        CenterDataAccount centerDataAccount = escBodyByAccount.getCenterDataAccount();
        PublicInfo publicInfo = escBodyByAccount.getPublicInfo();
        String businessType = publicInfo.getBusinessType();
        CurrentStartMarkParam currentStartMarkParam = centerDataAccount.getCurrentStartMarkParam();
        String startMark = currentStartMarkParam.getStartMark();
        String imageId = this.bizTranslist.getImageId();
        //取出网点发送到集中作业的报文值
        Map map = accountStartTest.getMap(escReceiveByCounterToAccount);
        //对公活期/财政性活期开户新建客户并开户
        EscCoreDto<EscResBody4010> escCoreDto4010 = null;
        EscCoreDto<EscResBody2110> escCoreDto2110 = null;

        //同业活期
        EscCoreDto<EscResBody4020> escCoreDto4020 = null;
        String clientNo = "";
        String clientNmCn = "";

        Map<String, Object> mapPost4010 = null;
        Map<String, Object> mapPost4020 = null;
        Map<String, Object> mapPost2110 = null;

        //用于最后报备账管等信息的集合
        Map<String, Object> mapPostManage = null;
        if (ChargeInfoEnum.CURRENT_NEW_OPEN.getCode().equals(startMark)) {

            //region 新建客户信息
            if (ChargeInfoEnum.PUBLIC_CURRENT.getCode().equals(businessType) || ChargeInfoEnum.FISCAL_CURRENT.getCode().equals(businessType)) {
                //对公活期--新建客户信息开户
                //先新建客户信息,获取传入值的所有字段值map集合
                //获取4010对公建立客户信息的除了集合和对象的所有字段
                PostCoreRecive postCoreRecive = this.coreService.core4010(this.bizTranslist, bizAccountmanageInfo, infoInputs, map);
                Boolean state = postCoreRecive.getState();
                if (state==false){
                    //建立客户信息失败
                    this.persistence.addEntity(this.bizTranslist);
                    this.persistence.addEntity(bizAccountmanageInfo);
                    return this.persistence;
                }else if (state==true){
                    //建立客户信息成功
                    escCoreDto4010=postCoreRecive.getEscCoreDto();
                    mapPost4010=postCoreRecive.getMap();
                    mapPostManage=postCoreRecive.getMap();
                }


            } else if (ChargeInfoEnum.PEERS_CURRENT.getCode().equals(businessType)) {
                //同业活期建立客户信息
                PostCoreRecive postCoreRecive = this.coreService.core4020(this.bizTranslist, bizAccountmanageInfo, infoInputs, map);
                Boolean state = postCoreRecive.getState();
                if (state==false){
                    //建立客户信息失败
                    this.persistence.addEntity(this.bizTranslist);
                    this.persistence.addEntity(bizAccountmanageInfo);
                    return this.persistence;
                }else if (state==true){
                    //建立客户信息成功
                    escCoreDto4020=postCoreRecive.getEscCoreDto();
                    mapPostManage=postCoreRecive.getMap();
                }
            }
            //endregion


        }else if (ChargeInfoEnum.PEERS_NEW_OPEN.getCode().equals(startMark)){
            //变更客户信息+开户
            //对公活期
            if (ChargeInfoEnum.PUBLIC_CURRENT.getCode().equals(businessType)||ChargeInfoEnum.FISCAL_CURRENT.getCode().equals(businessType)){

            }else if (ChargeInfoEnum.PEERS_CURRENT.getCode().equals(businessType)){
                PostCoreRecive postCoreRecive = this.coreService.core4022(this.bizTranslist, bizAccountmanageInfo, infoInputs, map);
                Boolean state = postCoreRecive.getState();
                if (state==false){
                    //变更客户信息失败
                    this.persistence.addEntity(this.bizTranslist);
                    this.persistence.addEntity(bizAccountmanageInfo);
                    return this.persistence;
                }else if (state==true){
                    //变更客户信息成功
                    escCoreDto4020=postCoreRecive.getEscCoreDto();
                    mapPostManage=postCoreRecive.getMap();
                }
            }
        }

        //region 对公活期开户
        PostCoreRecive postCoreRecive = this.coreService.core2110(this.bizTranslist, bizAccountmanageInfo, infoInputs, map);
        Boolean state = postCoreRecive.getState();
        if (state==false){
            //开户失败
            this.persistence.addEntity(this.bizTranslist);
            this.persistence.addEntity(bizAccountmanageInfo);
            return this.persistence;
        }else if (state==true){
            //开户成功
            escCoreDto2110=postCoreRecive.getEscCoreDto();
            mapPost2110=postCoreRecive.getMap();
        }
        //endregion

        //region 账管报备
        //去账管报备
        EscResBody2110 escResBody2110 = escCoreDto2110.getEscResBody();
        this.manageService.openAccountReport(mapPost2110,mapPostManage,escResBody2110,bizTranslist,bizAccountmanageInfo);
        //endregion


        //region 判断该交易记账有没自助回单、短信通等子交易
        HashOperations<String, Object, Object> opsForHash = redis.opsForHash();
        List<BizChargeMethods> bizChargeMethods = null;
        bizChargeMethods = (List<BizChargeMethods>) opsForHash.get("tran_code:" + bizTranslist.getTransCode(), "execute_mark:1");
        if (CollectionUtils.isEmpty(bizChargeMethods)) {
            QueryWrapper<BizChargeMethods> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tran_code", bizTranslist.getTransCode());
            queryWrapper.eq("execute_mark", "1");
            bizChargeMethods = bizChargeMethodsMapper.selectList(queryWrapper);
            opsForHash.put("tran_code:" + bizTranslist.getTransCode(), "execute_mark:1", bizChargeMethods);
        }
        if (bizChargeMethods.size() > 0) {
            ChargeSubTradeParam chargeSubTradeParam = new ChargeSubTradeParam();
            //从日志表中查询这一笔交易号传过来的报文
            chargeSubTradeParam.setSmsMark(currentStartMarkParam.getSmsMark());
            chargeSubTradeParam.setSelfList(currentStartMarkParam.getSelfList());
            chargeSubTradeParam.setPreSample(currentStartMarkParam.getPreSample());
            bizChargeMethods.forEach(bizChargeMethod -> {
                ReflectExecuteUtil.executeCharge(bizChargeMethod.getClassName(), bizChargeMethod.getServiceName(), chargeSubTradeParam);
            });
        }
        this.persistence.addEntity(this.bizTranslist);
        this.persistence.addEntity(bizAccountmanageInfo);
        //endregion
        return this.persistence;
    }
}
